package com.piece.file.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.piece.core.framework.annotation.permission.AclPermission;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.support.dto.UserDetailDTO;
import com.piece.core.framework.support.response.AjaxResponse;
import com.piece.core.framework.util.cache.CacheFactory;
import com.piece.core.framework.util.file.FileUtil;
import com.piece.core.framework.util.file.IoUtil;
import com.piece.core.framework.util.net.HttpUtil;
import com.piece.core.log.config.UserContextHolder;
import com.piece.core.web.controller.FrameWorkController;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.file.model.TbSysFile;
import com.piece.file.preview.FilePreviewFactory;
import com.piece.file.preview.FilePreviewHandle;
import com.piece.file.service.TbSysFileService;
import com.piece.file.support.FileAttribute;
import com.piece.file.support.WpsResponse;
import com.piece.file.util.WpsUtil;
import com.piece.file.client.FileClientFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.io.File;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.Scanner;

@Slf4j
@Controller
@RequestMapping("/office")
@Api(tags = {"Office在线文档管理"})
public class OfficePreviewController extends FrameWorkController {

    @Resource
    protected TbSysFileService tbSysFileService;

    @Resource
    protected FileClientFactory fileClientFactory;

    @Resource
    private WpsUtil wpsUtil;

    @Resource
    private FilePreviewFactory previewFactory;

    @Resource
    private CacheFactory cacheFactory;

    @AclPermission()
    @GetMapping(value = "/preview")
    @ApiOperation(value = "在线预览文档")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileId", value = "文件主键"),
            @ApiImplicitParam(name = "path", value = "文件本地地址"),
            @ApiImplicitParam(name = "url", value = "文件远程地址"),
            @ApiImplicitParam(name = "isOffice", value = "是否Office文件")
    })
    public String onlinePreview(Model model) {
        return forward(model, false);
    }

    @AclPermission()
    @RequestMapping(value = "/edit")
    @ApiOperation(value = "在线编辑文档")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileId", value = "文件主键"),
            @ApiImplicitParam(name = "path", value = "文件本地地址")
    })
    public String onlineEdit(Model model) {
        return forward(model, true);
    }

    private String forward(Model model, boolean edit) {
        String fileId = getRequest().getParameter("fileId");
        String filePath = getRequest().getParameter("path");
        String url = getRequest().getParameter("url");

        Object[] object;
        if (StringUtil.isNotEmpty(fileId)) {
            object = previewFactory.getByFileId(fileId);
        } else if (StringUtil.isNotEmpty(filePath)) {
            object = previewFactory.getByFilePath(filePath);
        } else {
            object = previewFactory.getByUrl(url);
        }

        model.addAttribute("userId", UserContextHolder.getUserId());
        model.addAttribute("userName", UserContextHolder.getUserName());
        FilePreviewHandle filePreviewHandle = (FilePreviewHandle) object[0];
        return filePreviewHandle.handle((FileAttribute) object[1], getRequest(), model , edit);
    }

    @ResponseBody
    @AclPermission()
    @PostMapping("/saveTxt")
    @ApiOperation(value = "在线保存文本文档")
    public AjaxResponse saveTxt() {
        String key = getRequest().getParameter("key");
        String content = getRequest().getParameter("content");
        try {
            key = FilePreviewFactory.FILE_CALLBACK_KEY + key;
            updateFile(key, IoUtil.toInputStream(content, Charset.forName("utf-8").name()));
            return success();
        } catch (Exception e) {
            return error(e.getMessage());
        }
    }

    private void updateFile(String key, InputStream is) throws Exception {
        FileAttribute fileAttribute = cacheFactory.get().get(key, FileAttribute.class);
        if (null != fileAttribute) {
            switch (fileAttribute.getSource()) {
                case path:
                    FileUtil.deleteFile(fileAttribute.getPath());
                    FileUtil.write(new File(fileAttribute.getPath()), is);
                    break;
                case file:
                    TbSysFile file = tbSysFileService.findById(Convert.toLong(fileAttribute.getPath()));
                    if (null != file) {
                        file.setFileInputStream(is);
                        fileClientFactory.get().updateFile(file);
                        is.close();
                    }
                    break;
            }
            cacheFactory.get().delete(key);
        }
    }

    @ResponseBody
    @AclPermission()
    @RequestMapping("/delete")
    @ApiOperation(value = "删除临时文档")
    public void delete() {
        String filePath = getRequest().getParameter("filePath");
        if (StringUtil.isNotEmpty(filePath)) {
            File tempFile = new File(filePath);
            if (tempFile.exists()) {
                tempFile.delete();
            }
        }
    }

    @ResponseBody
    @RequestMapping("/callback")
    @ApiOperation(value = "回调保存文档")
    public void callback() {
        try {
            PrintWriter writer = getResponse().getWriter();
            Scanner scanner = new Scanner(getRequest().getInputStream()).useDelimiter("\\A");
            String body = scanner.hasNext() ? scanner.next() : "";
            JSONObject jsonObj = JSON.parseObject(body);

            if((long) jsonObj.get("status") == 2) {
                String key = (String) jsonObj.get("key");
                key = FilePreviewFactory.FILE_CALLBACK_KEY + key;
                String downloadUri = (String) jsonObj.get("url");
                InputStream is = HttpUtil.get(downloadUri).execute().download();
                updateFile(key, is);
            }
            writer.write("{\"error\":0}");
        } catch (Exception e) {
            log.error("在线文档保存失败：{}",  e.getMessage());
        }
    }

    @ResponseBody
    @AclPermission()
    @GetMapping("/webViewUrl")
    @ApiOperation(value = "获取网络文件对应wps预览URL")
    @ApiImplicitParam(name = "url", value = "文件访问地址")
    public AjaxResponse webViewUrl() {
        String url =  getRequest().getParameter("url");
        WpsResponse response = wpsUtil.getViewUrl(url, true);
        return success(response);
    }

    @ResponseBody
    @AclPermission()
    @GetMapping("/createTemplate")
    @ApiOperation(value = "通过wps官方模版新建文件")
    @ApiImplicitParam(name = "template", value = "模板类型", allowableValues = "word,excel,ppt")
    public AjaxResponse createTemplate(UserDetailDTO user) {
        String template = getRequest().getParameter("template");
        Object newUrl = wpsUtil.createTemplateFile(template, user.getId());
        return success(newUrl);
    }
}
